/***************************************************************
 * Name:      mObject.cpp
 * Purpose:   opengl
 * Author:    Riku Maikola (rpm@ac-mapa.org)
 * Created:   2013-10-05
 * Copyright: Riku Maikola (rpm.ac-mapa.org)
 * License:
 **************************************************************/
#include "mObject.h"

oColor oC(double r,double g,double b,double a)
{
    oColor C;
    C.R=r;
    C.G=g;
    C.B=b;
    C.A=a;
    return C;
};

//*************************************************************//
//**
//**            mObject
//**
//*************************************************************//
void mObject::add( uint ID , mPoint p , oColor c , mPoint n )
{
    vbo point;

    union
    {
        unsigned int num;
        unsigned char ch[4];
    } data;

    data.num = ID;
    point.id[2] = data.ch[0];
    point.id[1] = data.ch[2];
    point.id[0] = data.ch[1];

    point.x = p.x;
    point.y = p.y;
    point.z = p.z;

    point.nx = n.x;
    point.ny = n.y;
    point.nz = n.z;

    point.r = c.R;
    point.g = c.G;
    point.b = c.B;
    point.a = c.A;

    dta.push_back(point);

}

void mObject::add(mPoint p1,mPoint p2, mPoint p3, oColor color)
{
     mPoint U,V,N;
     U.SetValue(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z);
     V.SetValue(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z);
     N.SetValue((U.y*V.z)-(U.z*V.y),(U.z*V.x)-(U.x*V.z),(U.x*V.y)-(U.y*V.x));
     N.normalize();

     add(0,p1,color,N);
     add(0,p2,color,N);
     add(0,p3,color,N);
}

void mObject::add(mPointArray A, oColor C ,double W,uint ID )
{
    width = W;
    for(uint a=0; a<A.size(); a++)
        add(ID,A[a],C);
}

//*****************************************************************//
//**
//*****************************************************************//
#include <wx/textfile.h>
#include <wx/tokenzr.h>
void mObject::load(wxString filename,mPoint T,double kerroin)
{
    wxString str;
    wxTextFile file;
    if(!file.Open(filename))
        return;

    bool Draw=false;
    uint A=0;
    for(size_t a=0; a<file.GetLineCount(); a++)
    {
        str = file.GetLine(a) << _("\n");

        wxStringTokenizer tkz(str, wxT(" "),wxTOKEN_STRTOK);
        mPoint p[3];

        while ( tkz.HasMoreTokens() )
        {
            wxString token = tkz.GetNextToken();

            if( token.Matches(_("outer")))
            {
                A=0;
                continue;
            }

            if( token.Matches(_("endsolid")))break;

            if( token.Matches(_("facet")))continue;
            if( token.Matches(_("endfacet\n")))continue;
            if( token.Matches(_("normal")))continue;
            if( token.Matches(_("loop\n")))continue;

            if( token.Matches(_("vertex"))&& (tkz.CountTokens()==3))
            {

                double value;
                tkz.GetNextToken().ToDouble(&value);
                double v1 = value*kerroin+T.x;
                tkz.GetNextToken().ToDouble(&value);
                double v2 = value*kerroin+T.y;
                tkz.GetNextToken().ToDouble(&value);
                double v3 = value*kerroin+T.z;

                p[A] = mP(v1,v2,v3);
                A++;
                continue;
            }

            if( token.Matches(_("endloop\n")) )
            {
                add(p[0],p[1],p[2],oC(0,0,0));
                continue;
            }
        }
    }
}

//*********************************************************************************//
//**
//*********************************************************************************//
void mObject::Lathe(mPointArray * P, oColor C,double accu)
{
    //TOP // DOWN
    double sek=TAU/accu;

    uint z=0;
    mPoint p1,p2,p3,p4,p5,p6;

    //*ALKU
    for(double r=0; r<(TAU-sek); r=r+sek)
    {
        p1.SetValue(cos(r)*P->at(z).x ,       sin(r)*P->at(z).x ,      P->at(z).y );
        p2.SetValue(cos(r)*P->at(z+1).x ,     sin(r)*P->at(z+1).x,     P->at(z+1).y);
        p3.SetValue(cos(r-sek)*P->at(z).x,    sin(r-sek)*P->at(z).x,   P->at(z).y);
        p4.SetValue(cos(r-sek)*P->at(z+1).x,  sin(r-sek)*P->at(z+1).x, P->at(z+1).y);
        p5.SetValue(cos(r-sek)*P->at(z).x,    sin(r-sek)*P->at(z).x,   P->at(z).y);
        p6.SetValue(cos(r)*P->at(z+1).x ,     sin(r)*P->at(z+1).x,     P->at(z+1).y);

        add(p4,p5,p6,oC(1,1,1));
    }

    //*******
    for(z=1; z<P->size()-2; z++)
    {
        for(double r=0; r<(TAU-sek); r=r+sek)
        {

            p1.SetValue(cos(r)*P->at(z).x ,       sin(r)*P->at(z).x ,      P->at(z).y );
            p2.SetValue(cos(r)*P->at(z+1).x ,     sin(r)*P->at(z+1).x,     P->at(z+1).y);
            p3.SetValue(cos(r-sek)*P->at(z).x,    sin(r-sek)*P->at(z).x,   P->at(z).y);
            p4.SetValue(cos(r-sek)*P->at(z+1).x,  sin(r-sek)*P->at(z+1).x, P->at(z+1).y);
            p5.SetValue(cos(r-sek)*P->at(z).x,    sin(r-sek)*P->at(z).x,   P->at(z).y);
            p6.SetValue(cos(r)*P->at(z+1).x ,     sin(r)*P->at(z+1).x,     P->at(z+1).y);

            add(p1,p2,p3,oC(1,1,1));

            //the OTHE

            add(p4,p5,p6,oC(1,1,1));
        }
    }

    for(double r=0; r<(TAU-sek); r=r+sek)
    {
        p1.SetValue(cos(r)*P->at(z).x ,       sin(r)*P->at(z).x ,      P->at(z).y );
        p2.SetValue(cos(r)*P->at(z+1).x ,     sin(r)*P->at(z+1).x,     P->at(z+1).y);
        p3.SetValue(cos(r-sek)*P->at(z).x,    sin(r-sek)*P->at(z).x,   P->at(z).y);
        p4.SetValue(cos(r-sek)*P->at(z+1).x,  sin(r-sek)*P->at(z+1).x, P->at(z+1).y);
        p5.SetValue(cos(r-sek)*P->at(z).x,    sin(r-sek)*P->at(z).x,   P->at(z).y);
        p6.SetValue(cos(r)*P->at(z+1).x ,     sin(r)*P->at(z+1).x,     P->at(z+1).y);

        add(p1,p2,p3,oC(1,1,1));

    }
}

void mObject::clear()
{
    dta.clear();
}

//************************************************//
//**                                            **//
//************************************************//
void mObject::render()
{
    if(dta.size()==0)return;
    if(show==false)return;
    if(GL_TRIANGLES == TYPE)
    {
         glEnable(GL_LIGHTING);
    }


    glLineWidth (width);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glVertexPointer(3, GL_FLOAT,sizeof(vbo),(char*)&dta[0]+20);
    glNormalPointer(GL_FLOAT,sizeof(vbo),(char*)&dta[0]+32);
    glColorPointer(4,GL_FLOAT,sizeof(vbo),(char*)&dta[0]+4);

    glDrawArrays(TYPE, 0, dta.size());

    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

     glDisable(GL_LIGHTING);

};

void mObject::render(oColor C,double width)
{
    if(dta.size()==0)return;
    if(show==false)return;

    glLineWidth (width);
    glColor3f(C.R,C.G,C.B);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT,  sizeof(vbo),(char*)&dta[0]+20);
    glDrawArrays(TYPE, 0, dta.size());
    glDisableClientState(GL_VERTEX_ARRAY);
};

void mObject::renderID()
{
    if(dta.size()==0)return;
    if(show==false)return;

    glLineWidth (3);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(3, GL_FLOAT,sizeof(vbo),(char*)&dta[0]+20);
    glColorPointer(3,GL_UNSIGNED_BYTE,sizeof(vbo),(char*)&dta[0]);
    glDrawArrays(TYPE, 0, dta.size());
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
};
//*************************************************************************************//
//**                                                                                 **//
//**                                                                                 **//
//**                                                                                 **//
//*************************************************************************************//
uint mObjectCTRL::addToList(GLuint type)
{
    mObject El;
    El.TYPE = type;
    O.push_back(El);
    return O.size()-1;
};
//*************************************************************************************//
//**                                                                                 **//
//**                                                                                 **//
//**                                                                                 **//
//*************************************************************************************//
void mObjectCTRL::render()
{
    for(uint a=0; a<O.size(); a++)
    {
        O[a].render();
    }
};



